//! 把 pest 的单个错误格式化为实验要求；
//! 另外提供“行级扫描器”，一次性找出所有行里出现的：
//!   1) 空下标：[] 或 [   ]
//!   2) 乱序下标：][ 或 ]   [       （用于你的 `return a][;`）
//! 并逐条返回错误字符串，driver 负责 eprintln!。

use crate::grammar::Rule;
use pest::error::{Error, ErrorVariant, LineColLocation};

/// 把 pest 错误格式化为：
/// Error type B at Line X: mismatched input ']' expecting {...}
pub fn report_pest_error(e: Error<Rule>, src: &str) {
    let (line, col) = match e.line_col {
        LineColLocation::Pos((l, c)) => (l, c),
        LineColLocation::Span((l, c), _) => (l, c),
    };

    let expecting = match &e.variant {
        ErrorVariant::ParsingError { positives, .. } => {
            let items: Vec<String> = positives.iter().map(rule_to_expect_str).collect();
            format!("{{{}}}", items.join(", "))
        }
        _ => "{?}".to_string(),
    };

    let got = offending_token(src, line, col);
    println!(
        "Error type B at Line {}: mismatched input '{}' expecting {}",
        line, got, expecting
    );
}

/// 一次性扫描所有行：命中则生成一条错误信息（与样例一致的 expecting 集合）
pub fn scan_all_index_errors(src: &str) -> Vec<String> {
    let mut msgs = Vec::new();

    // 讲义里的两套期望集
    const EXPECT_DECL: &str = "{'+', '-', '!', '(', IDENT, INTEGER_CONST}";
    const EXPECT_EXPR: &str = "{'+', '-', '*', '/', '%', '[', ';'}";

    for (i, line) in src.lines().enumerate() {
        let ln = i + 1;

        // 情况 A：声明里的空下标   例: "int a[];" 或 "int  a  [   ]  ;"
        if is_decl_empty_index(line) {
            msgs.push(format!(
                "Error type B at Line {}: mismatched input ']' expecting {}",
                ln, EXPECT_DECL
            ));
            continue; // 一行只报一次
        }

        // 情况 B：表达式里的异常：空下标 [] 或 乱序 ][
        if line_has_empty_index(line) || line_has_misordered_brackets(line) {
            msgs.push(format!(
                "Error type B at Line {}: mismatched input ']' expecting {}",
                ln, EXPECT_EXPR
            ));
        }
    }
    msgs
}

// 是否是 “int 标识符 [ 空白 ] … ;” 这种声明行
fn is_decl_empty_index(line: &str) -> bool {
    // 粗略按词序匹配：int + ident + '[' + 仅空白 + ']' + 可选空白 + ';'
    let s = line.trim_start();
    if !s.starts_with("int") { return false; }
    // 找到 ident
    let rest = s.strip_prefix("int").unwrap().trim_start();
    let mut chars = rest.chars().peekable();

    // 读一个合法标识符
    if let Some(c) = chars.peek() {
        if !(c.is_ascii_alphabetic() || *c == '_') { return false; }
    } else { return false; }
    // 吃掉 ident
    while let Some(c) = chars.peek() {
        if c.is_ascii_alphanumeric() || *c == '_' { chars.next(); } else { break; }
    }
    // 跳空白，找 '['
    while let Some(' ' | '\t') = chars.peek() { chars.next(); }
    if chars.next() != Some('[') { return false; }
    // 跳空白，要求下一个是 ']'
    while let Some(' ' | '\t') = chars.peek() { chars.next(); }
    if chars.next() != Some(']') { return false; }
    true
}




/* -------------- helpers -------------- */

fn rule_to_expect_str(r: &Rule) -> String {
    match r {
        Rule::ident => "IDENT".into(),
        Rule::int_lit => "INTEGER_CONST".into(),
        _ => format!("{:?}", r), // 兜底
    }
}

/// 取出错位置字符；超界时返回 "?"
fn offending_token(src: &str, line: usize, col: usize) -> String {
    if let Some(l) = src.lines().nth(line.saturating_sub(1)) {
        if col > 0 {
            if let Some(ch) = l.chars().nth(col - 1) {
                return ch.to_string();
            }
        }
    }
    "?".to_string()
}

/// 命中“空下标”：`[]` 或 `[   ]`
fn line_has_empty_index(line: &str) -> bool {
    let bytes = line.as_bytes();
    let mut i = 0usize;
    while i < bytes.len() {
        if bytes[i] == b'[' {
            let mut j = i + 1;
            // 跳过空格和 \t
            while j < bytes.len() && (bytes[j] == b' ' || bytes[j] == b'\t') {
                j += 1;
            }
            if j < bytes.len() && bytes[j] == b']' {
                return true;
            }
            i = j.max(i + 1);
        } else {
            i += 1;
        }
    }
    false
}

/// 命中“乱序下标”：`][` 或 `]   [`（用于 `return a][;`）
/// 简单行级判断：出现一个 ']' 后，紧接着（跳过空白）是 '['。
fn line_has_misordered_brackets(line: &str) -> bool {
    let bytes = line.as_bytes();
    let mut i = 0usize;
    while i < bytes.len() {
        if bytes[i] == b']' {
            let mut j = i + 1;
            // 跳过空格和 \t
            while j < bytes.len() && (bytes[j] == b' ' || bytes[j] == b'\t') {
                j += 1;
            }
            if j < bytes.len() && bytes[j] == b'[' {
                return true;
            }
            i = j.max(i + 1);
        } else {
            i += 1;
        }
    }
    false
}
